{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2-1张量数据结构\n",
    "\n",
    "程序 = 数据结构+算法。\n",
    "\n",
    "TensorFlow程序 = 张量数据结构 + 计算图算法语言\n",
    "\n",
    "张量和计算图是 TensorFlow的核心概念。\n",
    "\n",
    "Tensorflow的基本数据结构是张量Tensor。张量即多维数组。Tensorflow的张量和numpy中的array很类似。\n",
    "\n",
    "从行为特性来看，有两种类型的张量，常量constant和变量Variable.\n",
    "\n",
    "**常量的值在计算图中不可以被重新赋值，变量可以在计算图中用assign等算子重新赋值。**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 一，常量张量"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "张量的数据类型和numpy.array基本一一对应。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "\n",
    "i = tf.constant(1) # tf.int32 类型常量\n",
    "l = tf.constant(1, dtype=tf.int64) # tf.int64 类型常量\n",
    "f = tf.constant(1.23) # tf.float32 类型常量\n",
    "d = tf.constant(3.23, dtype=tf.double) #tf.double 类型常量\n",
    "s = tf.constant(\"hello world\") # tf.string 类型常量\n",
    "b = tf.constant(True) # tf.bool 类型常量\n",
    "\n",
    "print(tf.int64 == np.int64)\n",
    "print(tf.bool == np.bool)\n",
    "print(tf.double == np.float64)\n",
    "print(tf.string == np.unicode) # tf.string类型和np.unicode类型不等价"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "不同类型的数据可以用不同维度(rank)的张量来表示。\n",
    "\n",
    "标量为0维张量，向量为1维张量，矩阵为2维张量。\n",
    "\n",
    "彩色图像有rgb三个通道，可以表示为3维张量。\n",
    "\n",
    "视频还有时间维，可以表示为4维张量。\n",
    "\n",
    "可以简单地总结为：有几层中括号，就是多少维的张量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(0, shape=(), dtype=int32)\n",
      "0\n"
     ]
    }
   ],
   "source": [
    "#标量，0维张量\n",
    "scalar = tf.constant(True) \n",
    "print(tf.rank(scalar))\n",
    "print(scalar.numpy().ndim) # tf.rank的作用和numpy的ndim方法相同"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(1, shape=(), dtype=int32)\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "#向量，1维张量\n",
    "vector = tf.constant([1.0, 2.0, 3.0, 4.0]) \n",
    "\n",
    "print(tf.rank(vector))\n",
    "print(np.ndim(vector.numpy()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "#矩阵, 2维张量\n",
    "matrix = tf.constant([[1.0,2.0],[3.0,4.0]]) \n",
    "\n",
    "print(tf.rank(matrix).numpy())\n",
    "print(np.ndim(matrix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(\n",
      "[[[1. 2.]\n",
      "  [3. 4.]]\n",
      "\n",
      " [[5. 6.]\n",
      "  [7. 8.]]], shape=(2, 2, 2), dtype=float32)\n",
      "tf.Tensor(3, shape=(), dtype=int32)\n"
     ]
    }
   ],
   "source": [
    "# 3维张量\n",
    "tensor3 = tf.constant([[[1.0,2.0],[3.0,4.0]],[[5.0,6.0],[7.0,8.0]]])  \n",
    "print(tensor3)\n",
    "print(tf.rank(tensor3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(\n",
      "[[[[1. 1.]\n",
      "   [2. 2.]]\n",
      "\n",
      "  [[3. 3.]\n",
      "   [4. 4.]]]\n",
      "\n",
      "\n",
      " [[[5. 5.]\n",
      "   [6. 6.]]\n",
      "\n",
      "  [[7. 7.]\n",
      "   [8. 8.]]]], shape=(2, 2, 2, 2), dtype=float32)\n",
      "tf.Tensor(4, shape=(), dtype=int32)\n"
     ]
    }
   ],
   "source": [
    "# 4维张量\n",
    "tensor4 = tf.constant([[[[1.0,1.0],[2.0,2.0]],[[3.0,3.0],[4.0,4.0]]],\n",
    "                        [[[5.0,5.0],[6.0,6.0]],[[7.0,7.0],[8.0,8.0]]]])  \n",
    "print(tensor4)\n",
    "print(tf.rank(tensor4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以用tf.cast改变张量的数据类型。\n",
    "\n",
    "可以用numpy方法将tensorflow中的张量转化成numpy中的张量。\n",
    "\n",
    "可以用shape方法查看张量的尺寸。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<dtype: 'int32'> <dtype: 'float32'>\n"
     ]
    }
   ],
   "source": [
    "h = tf.constant([123, 456], dtype=tf.int32)\n",
    "f = tf.cast(h, tf.float32)\n",
    "print(h.dtype, f.dtype)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 2.]\n",
      " [3. 4.]]\n",
      "(2, 2)\n"
     ]
    }
   ],
   "source": [
    "y = tf.constant([[1.0, 2.0], [3.0, 4.0]])\n",
    "print(y.numpy())\n",
    "print(y.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b'\\xe4\\xbd\\xa0\\xe5\\xa5\\xbd \\xe4\\xb8\\x96\\xe7\\x95\\x8c'\n",
      "你好 世界\n"
     ]
    }
   ],
   "source": [
    "u = tf.constant(u\"你好 世界\")\n",
    "print(u.numpy())\n",
    "print(u.numpy().decode(\"utf-8\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 二，变量张量\n",
    "\n",
    "模型中需要被训练的参数一般被设置成变量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor([1. 2.], shape=(2,), dtype=float32)\n",
      "5453451336\n",
      "tf.Tensor([2. 4.], shape=(2,), dtype=float32)\n",
      "5453468392\n"
     ]
    }
   ],
   "source": [
    "# 常量值不可以改变，常量的重新赋值相当于创造新的内存空间\n",
    "c = tf.constant([1.0, 2.0])\n",
    "print(c)\n",
    "print(id(c))\n",
    "c = c + tf.constant([1.0, 2.0])\n",
    "print(c)\n",
    "print(id(c))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<tf.Variable 'V:0' shape=(2,) dtype=float32, numpy=array([1., 2.], dtype=float32)>\n",
      "5453322224\n",
      "<tf.Variable 'V:0' shape=(2,) dtype=float32, numpy=array([2., 3.], dtype=float32)>\n",
      "5453322224\n"
     ]
    }
   ],
   "source": [
    "# 变量的值可以改变，可以通过assign, assign_add等方法给变量重新赋值\n",
    "v = tf.Variable([1.0, 2.0], name=\"V\")\n",
    "print(v)\n",
    "print(id(v))\n",
    "v.assign_add([1.0, 1.0])\n",
    "print(v)\n",
    "print(id(v))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
